#include "../header.h"


//TODO 基于TCP协议的 服务器编程
//1.建立套接字 socket
//2.绑定：IP + PORT + 协议族
//3.监听 listen：
//4.链接 accept：用来建立连接  客户端套接字用来将进行读写。
//5.读写：套接字；一种文件类型-可以读写的文件。
//6.关闭套接字

/**
 * @函数原型: int socket(int domain, int type, int protocol);
 * @函数功能: create an endpoint for communication 建立一个套接字链接
 * @参数说明: 
 * @       参数1: domain 协议族
 * @       参数2: type 套接字类型： SOCK_STREAM  SOCK_DGRAM SOCK_RAW 
 * @       参数3: protocol : 0
 * @返回值: 服务端套接字 文件描述符。  
 * @param {int} argc
 */

/**
 * @函数原型: int bind(int sockfd, const struct sockaddr *addr,socklen_t addrlen);
 * @函数功能: bind a name to a socket 把ip port 协议族 - 绑定到网卡上。
 * @参数说明: 
 * @       参数1: sockfd  ： sid
 * @       参数2: struct sockaddr addr ： 函数使用的地址结构体。
 * @       参数3: addrlen ： 地址结构体长度
 * @返回值: 成功 0  失败  -1；
 *  On success, zero is returned.  On error, -1 is returned,
 * @param {int} argc
 */

/**
 * @函数原型:  int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
 * @函数功能: accept a connection on a socket   建立链接。
 * @参数说明: 
 * @       参数1: sockfd ： 服务端套接字 sid
 * @       参数2: struct sockaddr *addr ： 客户端地址结构体。
 * @       参数3: socklen_t *addrlen ： 地址结构体大小的地址。
 * @返回值: 客户端套接字  cid。
 * @param {int} argc
 */
int main(int argc, char const *argv[])
{
    //1.
    int sid = socket(AF_INET,SOCK_STREAM,0);
    printf("建立套接字成功:服务端端套接字:%d\n",sid);
    struct sockaddr_in saddr = {0};
    //IPV4协议族
    saddr.sin_family = AF_INET;
    //端口号
    saddr.sin_port = htons(10001);
    //IP地址
    saddr.sin_addr.s_addr = inet_addr("127.0.0.1");
    //2.绑定
    if(bind(sid,(struct sockaddr*)&saddr,sizeof(saddr)) < 0 )
    {
        perror("bind error\n");
        return -1;
    }
    printf("bind is successful\n");

    //3.监听。是否有客户端套接字与本套接字链接请求。
    //最大链接请求数。
    listen(sid,10);

    //4.链接。
    struct sockaddr_in caddr = {0};
    int size = sizeof(caddr);
    //阻塞，如果没有客户端的连接，就一直阻塞，如果有客户端的连接，就向下执行。
    int cid = accept(sid,(struct sockaddr*)&caddr,&size);
    printf("客户端套接字为:%d\n",cid);
    //打印出客户端的 详细信息

    char ipk[16] = "";
    printf("客户端的ip地址:%s\n",inet_ntop(AF_INET,&caddr.sin_addr.s_addr,ipk,sizeof(ipk)));
    printf("客户端的端口号:%d\n",ntohs(caddr.sin_port));
    
    printf("读写操作------------------------\n");
    close(cid);
    close(sid);
    return 0;
}
